/* 
 * File:   RepoItem.cpp
 * Author: gabilan
 * 
 * Created on 26 de mayo de 2013, 20:12
 */

#include <sstream>
#include <stdint.h>
#include "common_RepoItem.h"
#include "common_ProtocoloConstantes.h"

using namespace std;
using namespace TP::Archivos;

std::string RepoItem::_rootNodeName = "RepoItem";
std::string RepoItem::_versionNodeName = "Version";
std::string RepoItem::_filenameNodeName = "Filename";
std::string RepoItem::_filepathNodeName = "Filepath";
std::string RepoItem::_listOfHashesNodeName = "ListOHashes";
std::string RepoItem::_hashesNodeName = "Hash";
std::string RepoItem::_estadoNodeName = "Estado";

RepoItem::RepoItem() {
    _version = 0;
    _estado = ARCHIVO_INDEF;
    _filename = string("");
    _filepath = string("");    
}

RepoItem::~RepoItem() {
}

string RepoItem::GetRutaCompletaArchivo (){
    string ruta = _filepath;
    ruta += SEPARADOR_NODO;
    ruta += _filename;
    return ruta;
}

size_t RepoItem::GetCantidadHashes(){
    return _hashes.size();
}

std::string RepoItem::GetFilename() const {
    return this->_filename;
}

std::string RepoItem::GetFilePath() const {
    return this->_filepath;
}

string RepoItem::GetHash(const size_t &pIndice) const {
    
    if (pIndice < _hashes.size())
    {
        return this->_hashes[pIndice];
    }
    
    return string("");
}

void RepoItem::SetFilename(const string & s){
    this->_filename = s;
}

void RepoItem::SetFilePath(const string & s){
    this->_filepath = s;
}

uint32_t RepoItem::GetVersion ()
{
    return _version;
}

uint32_t RepoItem::SetVersion (const uint32_t &pValor)
{
    _version = pValor;
    return _version;
}

void RepoItem::AddHash(const string &s) {
    this->_hashes.push_back(s);
}

TiXmlNode* RepoItem::ToXml() {
    std::stringstream ss;
    
    TiXmlElement* rootNode = new TiXmlElement(_rootNodeName.c_str());
    
    // _version
    TiXmlElement* versionNode = new TiXmlElement(_versionNodeName.c_str());
    
    ss << _version;
    std::string versionStr(ss.str());
    ss.str("");
    
    TiXmlText* version = new TiXmlText(versionStr.c_str());        
    versionNode->LinkEndChild(version);    
    
    // _filename
    TiXmlElement* fileNameNode = new TiXmlElement(_filenameNodeName.c_str());
    TiXmlText* fileName = new TiXmlText(_filename.c_str());
    fileNameNode->LinkEndChild(fileName);
    
    
    // _filepath
    TiXmlElement* filePathNode = new TiXmlElement(_filepathNodeName.c_str());
    TiXmlText* filePath = new TiXmlText(_filepath.c_str());
    filePathNode->LinkEndChild(filePath);
    
    
    // List of hashes
    TiXmlElement* listOfHashesNode = new TiXmlElement(_listOfHashesNodeName.c_str());
    
    for (int i = 0; i < _hashes.size(); i++) {
        TiXmlElement* hashNode= new TiXmlElement(_hashesNodeName.c_str());
        TiXmlText* hash = new TiXmlText(_hashes[i].c_str());
        
        hashNode->LinkEndChild(hash);
        listOfHashesNode->LinkEndChild(hashNode);
    }

    // _estado
    TiXmlElement* estadoNode = new TiXmlElement(_estadoNodeName.c_str());
    std::stringstream strstm;
    strstm << _estado;
    TiXmlText* estado = new TiXmlText(strstm.str().c_str());
    estadoNode->LinkEndChild(estado);
    
    rootNode->LinkEndChild(versionNode);
    rootNode->LinkEndChild(fileNameNode);
    rootNode->LinkEndChild(filePathNode);
    rootNode->LinkEndChild(listOfHashesNode);
    rootNode->LinkEndChild(estadoNode);
    
    return rootNode;
}


string RepoItem::Serializar() {
    TiXmlDocument doc;
    TiXmlNode* rootNode = this->ToXml();    
    
    doc.LinkEndChild(rootNode);
    
    // Pasamos el doc a un string
    TiXmlPrinter printer;
    doc.Accept(&printer);
    
    std::string xmlDoc = printer.CStr();
    
    return xmlDoc;
}

RepoItem* RepoItem::Parse(TiXmlNode* xmlNode) {    
    
    if (NULL == xmlNode)
        return NULL;
    
    RepoItem* newRepoitem = new RepoItem();
    std::stringstream ss;   
    
    // _version
    TiXmlNode* versionNode = xmlNode->FirstChild(_versionNodeName.c_str());
    TiXmlNode* versionStr = versionNode->FirstChild();
    
    ss << versionStr->Value();
    uint32_t version;
    ss >> version;
    ss.str("");
    
    newRepoitem->SetVersion(version);
    
    
    // _filename
    TiXmlNode* filenameNode = xmlNode->FirstChild(_filenameNodeName.c_str());
    std::string filename = filenameNode->FirstChild()->Value();
    
    newRepoitem->SetFilename(filename);
    
    
    // _filepath
    TiXmlNode* filepathNode = xmlNode->FirstChild(_filepathNodeName.c_str());
    std::string filepath = filepathNode->FirstChild()->Value();
    
    newRepoitem->SetFilePath(filepath);
    
    // _hashes
    TiXmlNode* listOfHashesNode = xmlNode->FirstChild(_listOfHashesNodeName.c_str());
    TiXmlNode* hashNode = listOfHashesNode->FirstChild();
    
    while (hashNode) {
        if (hashNode->FirstChild())
        {
            std::string hash = hashNode->FirstChild()->Value();
            newRepoitem->AddHash(hash);
        }
        
        hashNode = hashNode->NextSibling();
    }
    
    // _estado
    TiXmlNode* estadoNode = xmlNode->FirstChild(_estadoNodeName.c_str());
    std::stringstream strstm;
    strstm << estadoNode->FirstChild()->Value();
    int32_t value;
    strstm >> value;
    newRepoitem->_estado = (estado_archivo_t) value;

    return newRepoitem;            
}

RepoItem* RepoItem::Parse(const string& pXml) {
    TiXmlDocument doc;   
    doc.Parse(pXml.c_str(), 0, TIXML_ENCODING_UTF8);    
    
    TiXmlNode* rootNode = doc.FirstChild(_rootNodeName.c_str());
    
    return RepoItem::Parse(rootNode);
}

RepoItem* RepoItem::Clonar() {
    
    RepoItem* item = new RepoItem();
    
    item->_estado = _estado;
    item->_filename = _filename;
    item->_filepath = _filepath;
    
    for (size_t i = 0; i < _hashes.size(); i++)
    {
        item->_hashes.push_back(_hashes[i]);
    }
    
    item->_version = _version;
    
    return item;
}
estado_archivo_t RepoItem::GetEstado(){
    return _estado;
}

estado_archivo_t RepoItem::SetEstado (estado_archivo_t pValor){
    _estado = pValor;
    return _estado;
}

void RepoItem::LimpiarHashes (){
    this->_hashes.clear();
}

